<?php

namespace Gql\Tools;

use GraphQL\Deferred;
use Illuminate\Contracts\Support\Arrayable;

class Buffer
{
    protected static $keys = [];

    protected static $loadHandle;

    protected static $filter;

    protected static $data;



    public static function add($keys):void
    {
        self::$keys[] = $keys;
    }

    public static function get($key):Deferred
    {
        $filter=self::$filter;
        return new Deferred(function () use ($filter, $key) {
            self::loadBuffered();
            $data = self::$data ?? [];
            if ($data instanceof Arrayable) $data = $data->toArray();
            return array_filter($data, function ($item) use ($filter, $key) {
                return call_user_func($filter, $item, $key);
            });
        });
    }


    public static function setHandle(callable $loadHandle): void
    {
        self::$loadHandle = $loadHandle;
    }
    public static function setFilter(callable $filter): void
    {
        self::$filter = $filter;
    }
    public static function load($key, callable $loadHandle, callable $filter):Deferred
    {
        self::add($key);
        self::setHandle($loadHandle);
        self::setFilter($filter);
        return self::get($key);
    }

    public static function getKeys():array
    {
        return self::$keys;
    }
    protected static function loadBuffered(): void
    {
        if (is_null(self::$data) && is_callable(self::$loadHandle)) {
            self::$data = call_user_func(self::$loadHandle, self::$keys);
        }
    }
}